package com.ninong.ker.admin.sevice.impl;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ninong.ker.admin.service.dto.UserDTO;
import com.ninong.ker.common.auth.JwtProperties;
import com.ninong.ker.common.auth.SecurityAdmin;
import com.ninong.ker.common.tools.PropertyUtil;
import com.ninong.ker.common.tools.SystemConstant;
import com.ninong.ker.common.user.OnlineUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ninong.ker.admin.domain.Dept;
import com.ninong.ker.admin.domain.User;
import com.ninong.ker.admin.domain.UserRole;
import com.ninong.ker.admin.mapper.DeptMapper;
import com.ninong.ker.admin.mapper.UserMapper;
import com.ninong.ker.admin.mapper.UserRoleMapper;
import com.ninong.ker.admin.sevice.UserService;
import com.ninong.ker.common.exception.CmdException;
import com.ninong.ker.common.tools.CmdAdminTools;
import com.ninong.ker.common.tools.Constants;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;

/**
 * @author cmd
 */
@Service
@Transactional(rollbackFor = RuntimeException.class)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

	private static final String PARENT = "0";
	private static final String TENANT_TYPE_0 = "0";
	private static final String TENANT_TYPE_1 = "1";

	@Autowired
	private DeptMapper deptMapper;
	@Autowired
	private UserRoleMapper userRoleMapper;
	@Autowired
	private SecurityAdmin securityAdmin;

	@Autowired
	private JwtProperties properties;

	@Override
	public PageInfo<User> listPage(UserDTO dto) {
		PageHelper.startPage(dto.getCurrentPage(), dto.getPageSize());
		OnlineUser online = securityAdmin.currentUser();
		if (StringUtils.equals(SystemConstant.ROOT_PARENT_ID, online.getTenantId())) {
			dto.setType(TENANT_TYPE_0);
		} else {
			dto.setType(TENANT_TYPE_1);
			dto.setTenantId(online.getTenantId());
		}
		dto.setDeleted(Constants.DEFAULT_YES);
		List<User> users = baseMapper.selectUserPage(dto);
		return new PageInfo<>(users);
	}

	@Override
	public void delete(String[] ids) {
		List<String> idList = Arrays.asList(ids);
		idList.forEach(id -> {
			Long count = userRoleMapper.selectCount(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, id));
			if (count > Constants.ZERO) {
				String mess = PropertyUtil.getProperty("USER_ROLE_EXIST");
				throw new CmdException(100, mess);
			}
			User entity = new User();
			entity.setId(id);
			entity.setDeleted(false);
			baseMapper.updateById(entity);
		});
	}

	@Override
	public void create(User entity) throws Exception {
		if (checkMobileExists(entity)) {
			String mess = PropertyUtil.getProperty("USER_PHONE_REPEAT");
			throw new CmdException(100, mess);
		}
		if (StringUtils.isEmpty(entity.getId())) {
			String salt = UUID.fastUUID().toString();
			entity.setSalt(salt);
			String password = SecureUtil.md5(salt + Constants.DEFAULT_PASSWORD);
			entity.setPassword(password);
			OnlineUser online = securityAdmin.currentUser();
			entity.setTenantId(online.getTenantId());
			entity.setType(TENANT_TYPE_1);
			entity.setDeleted(Constants.DEFAULT_YES);
			entity.setEnabled(Constants.DEFAULT_YES);
			entity.setUpdateTime(new Date());
		}
		this.saveOrUpdate(entity);
	}

	private boolean checkMobileExists(User dto) {
		if (StringUtils.isEmpty(dto.getPhone())) {
			throw new CmdException("手机号不能为空");
		}
		QueryWrapper<User> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(User::getPhone, dto.getPhone());
		queryWrapper.lambda().eq(User::getEnabled, Constants.DEFAULT_YES);
		queryWrapper.lambda().ne(User::getId, dto.getId());
		return baseMapper.selectOne(queryWrapper) != null;
	}

	@Override
	public User get(String id) {
		User entity = baseMapper.selectById(id);
		if (ObjectUtils.isEmpty(entity)) {
			entity = new User();
		}
		Dept dto = new Dept();
		OnlineUser online = securityAdmin.currentUser();
		dto.setPid(PARENT);
		dto.setTenantId(online.getTenantId());
		entity.setResouces(deptMapper.selectDeptTree(dto));
		return entity;
	}

	@Override
	public void enableUser(String id, Boolean enable) {
		User entity = new User();
		entity.setId(id);
		entity.setEnabled(enable);
		baseMapper.updateById(entity);
	}

	@Override
	public List<User> listUserTree() {
		LambdaQueryWrapper<User> query = new LambdaQueryWrapper<>();
		query.eq(User::getDeleted, Constants.DEFAULT_YES);
		query.select(User::getId, User::getNickName);
		List<User> users = baseMapper.selectList(query);
		return users;
	}

	@Override
	public List<User> selectTenantAdminUser(String tenantId) {
		List<User> userList = baseMapper.selectTenantAdminUser(tenantId);
		return userList;
	}

	@Override
	public void resetPassword(String userId) {
		User user = baseMapper.selectById(userId);
		if (BeanUtil.isEmpty(user)) {
			throw new CmdException("用户不存在");
		}
		String salt = UUID.fastUUID().toString();
		user.setSalt(salt);
		String password = SecureUtil.md5(salt + Constants.DEFAULT_PASSWORD);
		user.setPassword(password);
		baseMapper.updateById(user);

	}

	@Override
	public String changePassword(UserDTO dto, String token) throws Exception {
		// 用户id
		OnlineUser onlineUser = securityAdmin.currentUser(token);
		String id = onlineUser.getId();
		User user = baseMapper.selectById(id);
		// MD5加密后的用户输入密码
		dto.setOrginalPassword(CmdAdminTools.decryptByPrivateKey(properties.privateKey, dto.getOrginalPassword()));
		String password = SecureUtil.md5(user.getSalt() + dto.getOrginalPassword());
		if (!org.apache.commons.lang3.StringUtils.equals(user.getPassword(), password)) {
			throw new CmdException("原密码错误，请重新输入！");
		}
		// 设置新密码、盐值
		String salt = UUID.fastUUID().toString();
		user.setSalt(salt);
		dto.setPass(CmdAdminTools.decryptByPrivateKey(properties.privateKey, dto.getPass()));
		String newPassword = SecureUtil.md5(user.getSalt() + dto.getPass());
		user.setPassword(newPassword);
		baseMapper.updateById(user);
		return "修改密码成功！";
	}

}
